﻿using System.Security.RightsManagement;
using Infragistics;
using Infragistics.Controls.Charts;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using VNet.VisiSuite.Common;
using VNet.VisiSuite.Common.Helper;
using VNet.VisiSuite.Common.Logger;
using VNet.VisiSuite.Common.Resource;
using VNet.VisiSuite.Common.Security;
using VNet.VisiSuite.Controls;
using VNet.VisiSuite.Service.Contact.Message;
using VNet.VisiSuite.Service.Contact.Message.Base;
using VNet.VisiSuite.Service.Contact.Message.Item;
using VNet.VisiSuite.Service.Contact.Message.Security;
using VNet.VisiSuite.VisiBoard.BusinessLogic;
using VNet.VisiSuite.VisiBoard.Common;
using VNet.VisiSuite.VisiBoard.Common.Helpers;
using VNet.VisiSuite.VisiBoard.Controls;
using VNet.VisiSuite.VisiBoard.Models;
using VNet.VisiSuite.VisiBoard.Providers;
using VNet.VisiSuite.VisiBoard.Views;
using System.Windows.Input;
using VNet.VisiSuite.VisiBoard.Dal.EntityClasses;
using System.Windows.Threading;
using System.Diagnostics;
using VNet.VisiSuite.Common.Production;
using VNet.VisiSuite.Common.Helpers;
using VNet.VisiSuite.Service.Contact.Message.ProductionData;
using VNet.VisiSuite.VisiBoard.WebServer;

namespace VNet.VisiSuite.VisiBoard.ViewModels
{

    public class AveCycleTimes
    {
        public int AveCycleTime { get; set; }
        public int AveLoadUnloadTime { get; set; }
    }

    public class ProductionViewModel : BaseViewModel, VNet.VisiSuite.Common.Production.ProductionInterface
    {
        #region Fields
        private bool _processing_visibox_events = false;
        private ProductionModel _model;
        private Visibility _visibility;
        private bool _offline = false;
        private bool _redraw_error = false;

        private int _production_meter_width = 240;
        private SolidColorBrush _transparent = new SolidColorBrush(Colors.Transparent);
        private List<ProductionMeterGraphLegend> _legend = null;
        private readonly DispatcherTimer _production_meter_refresh_timer;

        private readonly DispatcherTimer _sync_timer;
        private bool _sync_in_progress = false;
        private Stopwatch _server_sync_stop_watch;

        private readonly DispatcherTimer _offline_timer;

        private VNet.VisiSuite.VisiBoard.BusinessLogic.LocalUtil.ProductionData _production_meter_data = null;

        private List<dynamic> _production_plans;
        private Visibility _circular_visibility = Visibility.Collapsed;
        private bool _show_dialog = false;

        private Visibility _countdown_timer_visibility = Visibility.Collapsed;
        private TimeSpan _countdown_time = TimeSpan.FromMinutes(1);

        private static SimpleWebServer _web_server = null;

        private VNetMenuItem _safety;
        private VNetMenuItem _quality;
        private VNetMenuItem _pre_setup;
        private VNetMenuItem _break_lunch;

        #endregion

        public RelayCommand DefectClickCommand { get; set; }

        public ProductionViewModel()
        {

            Model = new ProductionModel();
            Model.ShouldValidate = true;

            var visi_board = BusinessLogic.VisiBoard.instance();
            var visi_box = BusinessLogic.VisiBox.instance();
            visi_board.initialize(this.onProductionHistoryChange);
            visi_box.start(visi_board.CellName, visi_board.BraiderType, this.processVisiBoxEvents, App.PublishedVersion().ToString());

            PageTitle = "VisiBoard | " + visi_board.AreaName + " | " + visi_board.CellName;
            // TopRightButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem("Exit", "Exit VisiSuite", CommonConstants.VNetIcon.AppbarClose, VNetMenuItemType.WhiteBackgroundTheme, OnExit), };

            var bottom_menu = new ObservableCollection<VNetMenuItem>();
            bottom_menu.Add(new VNetMenuItem("Downtime", "Downtime", CommonConstants.VNetIcon.AppbarGraphBar, VNetMenuItemType.BlackBackgroundTheme, showDowntimeScreen));
            BottomMenuItems = bottom_menu;

            var top_menu = new ObservableCollection<VNetMenuItem>();
          //  top_menu.Add(new VNetMenuItem());

            DefectClickCommand = new RelayCommand(showScrapDialog);
            // startThreads();

            _production_meter_data = Model.productionMeterData();

            _legend = new List<ProductionMeterGraphLegend>();
            foreach (var lgd in _production_meter_data.Legend)
            {
                _legend.Add(new ProductionMeterGraphLegend(lgd.Description, new SolidColorBrush(Infragistics.ColorConverter.FromString(lgd.Color))));
            }

            // _production_meter_data.ProductionMeterFreq;
            GraphInterval = _production_meter_data.ProductionMeterWidth;

            _production_meter_refresh_timer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher.CurrentDispatcher)
            {
                Interval = new TimeSpan(0, 0, 0, 15, 0)
            };
            _production_meter_refresh_timer.Tick += refreshProductionMeter;
            _production_meter_refresh_timer.Start();

            _sync_timer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher.CurrentDispatcher)
            {
                Interval = new TimeSpan(0, 0, 2, 15, 0)
            };
            _sync_timer.Tick += syncData;
            _sync_timer.Start();
            _server_sync_stop_watch = new Stopwatch();
            _server_sync_stop_watch.Start();

            _offline_timer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher.CurrentDispatcher)
            {
                Interval = new TimeSpan(0, 0, 2, 1, 0)
            };
            _offline_timer.Tick += offline;

            startWebServer();
        }

        ~ProductionViewModel()
        {
            // Cleaning up
            _production_meter_refresh_timer.Stop();
            _production_meter_refresh_timer.Tick -= refreshProductionMeter;

            _sync_timer.Stop();
            _sync_timer.Tick -= syncData;
        }

        private void startWebServer()
        {
            if (_web_server == null)
            {
                // Start web server
                var hostname = SystemInfo.hostname();
                // run the following command as admin to allow VisiBoard to listen on port 8081
                // netsh http add urlacl url="http://*:8081/" user=everyone listen=yes
                string[] prefixes = { "http://*:8081/" }; 
                _web_server = new SimpleWebServer(prefixes, WebServerRequestHandler.requestHandler);
                _web_server.run(); // runs in a separate thread
            }
        }

        private void offline(object sender, EventArgs e)
        {
            _offline_timer.Stop();
            var visi_board = BusinessLogic.VisiBoard.instance();
            if (_offline)
                PageTitle = "VisiBoard | " + visi_board.AreaName + " | " + visi_board.CellName + " (offline)";
            else
                PageTitle = "VisiBoard | " + visi_board.AreaName + " | " + visi_board.CellName;
        }

        private void syncData(object sender, EventArgs e)
        {
            if (!_sync_in_progress)
            {
                _sync_in_progress = true;
                _sync_timer.Stop();

                BusinessLogic.VisiBoard.instance().updateCellStatus();

                DoAsync(SyncProvider.SyncDataFromClientToServer, syncToServerCompleted);
            }
        }

        private void syncToServerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            ServiceBaseResponse response = e.Result as ServiceBaseResponse;
            if (response.Success == false)
            {
                FileLog.Error("syncToServerCompleted() - " + response.Error.Description);
            }
            
            if (_server_sync_stop_watch.ElapsedMilliseconds > 120000)
            {
                DoAsync(SyncProvider.SyncDataFromServerToClient, syncFromServerCompleted, ClientSyncUtil.tableDataChanges());
            }
            else
            {
                _sync_timer.Start();
                _sync_in_progress = false;
            }
        }

        private void syncFromServerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            ServiceBaseResponse response = e.Result as ServiceBaseResponse;
            if (response.Success == false)
            {
                FileLog.Error("syncFromServerCompleted() - " + response.Error.Description);
            }

            _server_sync_stop_watch.Restart();
            _sync_timer.Start();
            _sync_in_progress = false;
    
        }

        private void refreshProductionMeter(object sender, EventArgs e)
        {
            var visi_board = BusinessLogic.VisiBoard.instance();
            if (visi_board.isEndShift())
            {
                visi_board.beginNextShift();
            }
            else
            {
                visi_board.refreshPrevProductionHistory();
            }
            DoAsync(calcAveCycleTime, calcAveCycleTimeCompleted);
        }

        private void calcAveCycleTime(object sender, DoWorkEventArgs e)
        {
            var worker = sender as BackgroundWorker;
            e.Result = null;

            if (worker != null && worker.CancellationPending == false)
            {
                var visi_board = BusinessLogic.VisiBoard.instance();                 
                double ave_cycle_time = 0;
                double ave_loadunload_time = 0;

                visi_board.calcAveCycleTime(out ave_cycle_time, out ave_loadunload_time);
                
                e.Result = new AveCycleTimes() {
                    AveCycleTime = (int)Math.Round(ave_cycle_time),
                    AveLoadUnloadTime = (int)Math.Round(ave_loadunload_time)
                };
                
            }
        }

        private void calcAveCycleTimeCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {

            var result = e.Result as AveCycleTimes;
            TimeSpan ts;
            if (result != null)
            {
                if (result.AveCycleTime > 0)
                {                    
                    ts = new TimeSpan(0, 0, result.AveCycleTime);
                    AverageCycleTime = string.Format("{0}:{1:00}", ts.Minutes, ts.Seconds);
                }
                else
                {
                    AverageCycleTime = "";
                }
                if (result.AveLoadUnloadTime > 0)
                {
                    ts = new TimeSpan(0, 0, result.AveLoadUnloadTime);
                    AverageLoadUnloadTime = string.Format("{0}:{1:00}", ts.Minutes, ts.Seconds);
                }
                else
                {
                    AverageLoadUnloadTime = "";
                }
            }
            else
            {
                AverageCycleTime = "";
                AverageLoadUnloadTime = "";
            }
            OnPropertyChanged("AverageCycleTime");
            OnPropertyChanged("AverageLoadUnloadTime");

            OnPropertyChanged("TargetCycleTime");
            OnPropertyChanged("TargetLoadUnloadTime");

        }

        private void onProductionHistoryChange(VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType ut, DateTime start, DateTime end, int rollup_id)
        {
            if (_production_meter_data != null)
            {
                int legend_idx = (int)(rollup_id > 0 ? _production_meter_data.Legend.FindIndex(x => x.RollupDefinitionId == rollup_id) : -1);
                try
                {
                    if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.UpdateLast)
                    {
                        int cnt = _production_meter_data.Data.Count;
                        if (cnt > 0)
                        {
                            if (legend_idx < 0)
                                legend_idx = _production_meter_data.Data[cnt - 1].Legend;
                            _production_meter_data.Data[cnt - 1] = new ProductionMeterDataPoint(start, end, legend_idx);
                        }
                        if (end.Minute < 3)
                        {
                            // so that it does not show blank
                            onProductionHistoryChange(BusinessLogic.VisiBoard.UpdateType.PartProduced, end, end, 0);
                        }

                    }
                    else if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.AddNew)
                    {
                        _production_meter_data.Data.Add(new ProductionMeterDataPoint(start, end, legend_idx));

                    }
                    else if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.NewShift)
                    {
                        _production_meter_refresh_timer.Stop();

                        _production_meter_data = Model.productionMeterData();
                        _legend = new List<ProductionMeterGraphLegend>();
                        foreach (var lgd in _production_meter_data.Legend)
                        {
                            _legend.Add(new ProductionMeterGraphLegend(lgd.Description, new SolidColorBrush(Infragistics.ColorConverter.FromString(lgd.Color))));
                        }

                        OnPropertyChanged("HeaderBrush");
                        OnPropertyChanged("HeaderTextBrush");
                        OnPropertyChanged("AxisDetails");
                        OnPropertyChanged("GraphStartTime");
                        OnPropertyChanged("GraphEndTime");
                        OnPropertyChanged("GraphInterval");
                        OnPropertyChanged("GraphDataPoints");
                        OnPropertyChanged("GraphLegend");

                        _production_meter_refresh_timer.Start();

                    }
                    else if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.Refresh)
                    {
                        _production_meter_refresh_timer.Stop();

                        _production_meter_data = Model.productionMeterData();
                        OnPropertyChanged("HeaderBrush");
                        OnPropertyChanged("AxisDetails");
                        OnPropertyChanged("HeaderTextBrush");
                        OnPropertyChanged("GraphDataPoints");

                        _production_meter_refresh_timer.Start();

                    }
                    else if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.PartProduced)
                    {
                        for (int ii=0; ii<_production_meter_data.Axis.Count; ++ii)
                        {
                            if (start < _production_meter_data.Axis[ii].EndTime && start >= _production_meter_data.Axis[ii].StartTime)
                            {
                                if (_production_meter_data.Axis[ii].Good.HasValue)
                                    _production_meter_data.Axis[ii].Good += rollup_id;
                                else
                                    _production_meter_data.Axis[ii].Good = rollup_id;
                                break;
                            }
                        }
                    }
                    else if (ut == VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.AddScrap)
                    {
                        for (int ii = 0; ii < _production_meter_data.Axis.Count; ++ii)
                        {
                            if (start < _production_meter_data.Axis[ii].EndTime && start >= _production_meter_data.Axis[ii].StartTime)
                            {
                                if (_production_meter_data.Axis[ii].Defect.HasValue)
                                    _production_meter_data.Axis[ii].Defect += rollup_id;
                                else
                                    _production_meter_data.Axis[ii].Defect = rollup_id;
                                break;
                            }
                        }
                    }

                }
                catch (Exception ex)
                {
                    FileLog.Error("onProductionHistoryChange", ex);
                }
            }

            switch (ut)
            {
                case VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.AddScrap:
                case VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.ForceSync:
                case VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.NewShift:
                    syncData(null, null);
                break;

                default:
                    break;
            }

        }


        #region Properties

       public Brush HeaderTextBrush
       {
           get { return _model.DowntimeForeground; }
       }

        public Brush HeaderBrush
        {
            get { return _model.DowntimeBackground; }
        }

        public ProductionModel Model
        {
            get { return _model; }
            set
            {
                _model = value;
                OnPropertyChanged("Model");
            }
        }

        public bool Offline
        {
            get { return _offline; }
            set
            {
                if (_offline != value)
                {
                    _offline_timer.Stop();
                    _offline = value;
                    var visi_board = BusinessLogic.VisiBoard.instance();
                    if (_offline)
                        _offline_timer.Start();
                    else
                        PageTitle = "VisiBoard | " + visi_board.AreaName + " | " + visi_board.CellName;
                }
            }

        }

        public bool RedrawError {
            get { return _redraw_error; }
            set
            {
                _redraw_error = value;
                if (_redraw_error)
                    onProductionHistoryChange(VNet.VisiSuite.VisiBoard.BusinessLogic.VisiBoard.UpdateType.Refresh, DateTime.MinValue, DateTime.MaxValue, -1);
            }
        }

        public DateTime GraphStartTime
        {
            get { return _production_meter_data.StartTime; }
        }

        public DateTime GraphEndTime
        {
            get { return _production_meter_data.EndTime; }
        }

        public List<ProductionMeterGraphLegend> GraphLegend
        {
            get { return _legend; }
        }


        public ObservableCollection<ProductionMeterDataPoint> GraphDataPoints
        {
            get { return _production_meter_data.Data;  }
            /*
            set
            {
                _production_meter_data = value;
                OnPropertyChanged("ProductionMeterData");
            }
             */
        }

        public int GraphInterval
        {
            get { return _production_meter_width; }
            set
            {
                if (_production_meter_width != value)
                {
                    _production_meter_width = value;
                    OnPropertyChanged("GraphInterval");
                }
            }
        }

        public Visibility Visibility
        {
            get { return _visibility; }
            set
            {
                _visibility = value;
                OnPropertyChanged("Visibility");
            }
        }


        public List<AxisDetailItem> AxisDetails
        {
            get
            {
                //return ProductionModel.productionMeterData().Axis;
                return _production_meter_data != null
                    ? _production_meter_data.Axis
                    : new List<AxisDetailItem>();
            }
        }

        public List<LegendItem> Legends
        {
            get
            {
                return _production_meter_data != null
                    ? _production_meter_data.Legend
                    : new List<LegendItem>();
                   
            }
        }

        public Visibility CountDownTimerVisibility
        {
            get { return _countdown_timer_visibility; }
            set
            {
                if (_countdown_timer_visibility != value)
                {
                    _countdown_timer_visibility = value;
                    OnPropertyChanged("CountDownTimerVisibility");
                }
            }
        }

        public TimeSpan CountDownTime
        {
            get { return _countdown_time; }
            set
            {
                _countdown_time = value;
                OnPropertyChanged("CountDownTime");
            }
        }

        public Visibility CircularVisibility
        {
            get { return _circular_visibility; }
            set
            {
                if (_circular_visibility != value)
                {
                    _circular_visibility = value;
                    OnPropertyChanged("CircularVisibility");
                }
            }
        }

        public Visibility PressToChangeVisibility
        {
            get { return Visibility.Visible; }
        }

        public Visibility DowntimeVisibility
        {
            get { return Model.IsMachineRunning ? Visibility.Hidden : Visibility.Visible; }
        }

        public string Operator 
        {
            get
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                return visi_board.OperatorName;
            }
        }

        public string DowntimeDescription
        {
            get {
                var desc = Model.DowntimeDescription;
                if (Model.IsLoadUnloadOverrun || (desc == "Load / Unload Overrun"))
                    desc = "Waiting for Operator";

                return  desc + "\nsince " + Model.DowntimeSince.ToString("d-MMM-yyyy h:mm tt");
            }
        }

        public Brush DowntimeBackground
        {
            get { return Model.DowntimeBackground; }
        }

        public Brush DowntimeForeground
        {
            get { return Model.DowntimeForeground; }
        }

        public GridLength DowntimeColumn1
        {
            get
            {
                return _show_dialog ? new GridLength(0) : new GridLength(1, GridUnitType.Star);
            }
        }

        public GridLength DowntimeColumn2
        {
            get
            {
                return _show_dialog ? new GridLength(1, GridUnitType.Star) : new GridLength(1, GridUnitType.Auto);
            }
        }

        public GridLength DowntimeColumn3
        {
            get
            {
                return _show_dialog ? new GridLength(375-22, GridUnitType.Pixel) : new GridLength(1, GridUnitType.Star);
            }
        }

        private void updateProductionPlans()
        {
            if (_production_plans == null || !_production_plans.Any())
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                _production_plans = visi_board.currentAndNextProductionPlans();
            }
        }

        public string TargetCycleTime
        {
            get
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                var time = "";
                var ts = new TimeSpan(0, 0, visi_board.TargetCycleTime);
                time = string.Format("{0}:{1:00}", ts.Minutes, ts.Seconds);
                return time;
            }
        }

        public string TargetLoadUnloadTime
        {
            get
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                var time = "";
                var ts = new TimeSpan(0, 0, visi_board.TargetLoadUnloadTime);
                time = string.Format("{0}:{1:00}", ts.Minutes, ts.Seconds);
                return time;
            }
        }

        public int TargetLoadUnloadSecs
        {
            get
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                return visi_board.TargetLoadUnloadTime;
            }
        }

        public string AverageCycleTime { get; set; }
        public string AverageLoadUnloadTime { get; set; }

        public string CurrentSku
        {
            get
            {
                updateProductionPlans();
                var sku = "";
                if (_production_plans.Any() && _production_plans[0] != null)
                    sku = _production_plans[0].Sku;
                return sku;
            }
        }

        private string stripWorkOrder(string work_order)
        {
            string val = work_order;
            try
            {
                int idx = work_order.IndexOf('-');
                if (idx >= 0)
                {
                    idx = work_order.IndexOf('-', idx + 1);
                    if (idx > 0)
                        val = work_order.Substring(0, idx);
                }
            }
            catch (Exception ex)
            {

            }
            return val;
        }

        public string CurrentWorkOrder
        {
            get
            {
                updateProductionPlans();
                var work_order = "";
                if (_production_plans.Any() && _production_plans[0] != null)
                    work_order = _production_plans[0].WorkOrder;
                return work_order;
            }
        }

        public string CurrentPass
        {
            get
            {
                updateProductionPlans();
                var pass = "";
                if (_production_plans.Any() && _production_plans[0] != null && _production_plans[0].OperationPass != null)
                    pass = _production_plans[0].OperationPass.ToString();
                return pass;
            }
        }

        public string CurrentQuantity
        {
            get
            {
                updateProductionPlans();
                var qty = "";
                if (_production_plans.Any() && _production_plans[0] != null)
                    qty = _production_plans[0].Planned.ToString("#,##0");
                return qty;
            }
        }

        public string CurrentRemaining
        {
            get
            {
                updateProductionPlans();
                string val = "";
                if (_production_plans.Any() && _production_plans[0] != null)
                {
                    var visi_board = BusinessLogic.VisiBoard.instance();
                    int remaining = _production_plans[0].Planned - _production_plans[0].Actual;
                    int good = 0;
                    int scrap = 0;
                    good = visi_board.goodAndScrap(_production_plans[0].ProductionPlanId, _production_plans[0].ActualDate, out scrap);
                    remaining -= good;
                    val = remaining.ToString("#,##0");
                }
                return val;
            }
        }

        public string NextSku
        {
            get
            {
                updateProductionPlans();
                var sku = "";
                if (_production_plans.Count() > 1 && _production_plans[1] != null)
                    sku = _production_plans[1].Sku;
                return sku;
            }
        }

        public string NextWorkOrder
        {
            get
            {
                updateProductionPlans();
                var work_order = "";
                if (_production_plans.Count() > 1 && _production_plans[1] != null)
                    work_order = _production_plans[1].WorkOrder;
                return work_order;
            }
        }

        public string NextPass
        {
            get
            {
                updateProductionPlans();
                var pass = "";
                if (_production_plans.Count() > 1 && _production_plans[1] != null && _production_plans[1].OperationPass != null)
                    pass = _production_plans[1].OperationPass.ToString();
                return pass;
            }
        }
        
        public string NextQuantity
        {
            get
            {
                updateProductionPlans();
                var qty = "";
                if (_production_plans.Count() > 1 && _production_plans[1] != null)
                    qty = _production_plans[1].Planned.ToString("#,##0");
                return qty;
            }
        }

        public string NextRemaining
        {
            get
            {
                updateProductionPlans();
                string val = "";
                if (_production_plans.Count() > 1 && _production_plans[1] != null)
                {
                    var visi_board = BusinessLogic.VisiBoard.instance();
                    int remaining = _production_plans[1].Planned - _production_plans[1].Actual;
                    int good = 0;
                    int scrap = 0;
                    good = visi_board.goodAndScrap(_production_plans[1].ProductionPlanId, _production_plans[1].ActualDate, out scrap);
                    remaining -= good;
                    val = remaining.ToString("#,##0");
                }
                return val;
            }
        }

        public string BreakTitle
        {
            get
            {
                string title = "Break / Lunch";
                var visi_board = BusinessLogic.VisiBoard.instance();
                ReasonCodeEntity break_lunch = (visi_board != null ? visi_board.Break : null);
                if (break_lunch != null)
                {
                    title = "End " + break_lunch.Description;
                }
                return title;
            }
        }


        public ObservableCollection<VNetMenuItem> TasksLeft
        {
            get
            {
                var tasks_left = new ObservableCollection<VNetMenuItem>();
                tasks_left.Add(_safety = new VNetMenuItem("Safety", "Safety", null, VNetMenuItemType.GreenWhiteTheme, null, "10"));
                tasks_left.Add(_quality = new VNetMenuItem("Quality", "Quality", null, VNetMenuItemType.GreenWhiteTheme, null, "10"));
                tasks_left.Add(_pre_setup = new VNetMenuItem("Pre-Setup", "Pre-Setup", null, VNetMenuItemType.RedWhiteTheme, null, "10"));
                _safety.IsEnabled = false;
                _quality.IsEnabled = false;
                _pre_setup.IsEnabled = false;

                return tasks_left;
            }
        }

        public ObservableCollection<VNetMenuItem> TasksRight
        {
            get
            {
                var tasks_right = new ObservableCollection<VNetMenuItem>();
                string title = BreakTitle;
                tasks_right.Add(_break_lunch = new VNetMenuItem(title, title, null, VNetMenuItemType.BlueWhiteTheme, showBreakLunchDialog));
                return tasks_right;
            }
        }

        public string TasksTitle
        {
            get { return "Tasks"; }
        }
                
        #endregion

        #region Methods

        private bool processVisiBoxEvents()
        {
            if (_processing_visibox_events)
                return false;

            _processing_visibox_events = true;

            VisiBoxEvent evt;
            int cnt = 0;  // limit the number of events processed to prevent an infinite loop because events are added to the queue from another thread - we need to call clearEvents()
            int new_cnt = 0;
            var visi_board = BusinessLogic.VisiBoard.instance();
            var visi_box = BusinessLogic.VisiBox.instance();

            bool was_running = visi_board.IsMachineRunning;

            try
            {

                // Loop thru all the events
                while (visi_box.dequeueEvent(out evt) && cnt < 100)
                {
                    if (visi_board.processVisiBoxEvent(evt))
                    {
                        if (visi_board.IsMachineRunning)
                            was_running = true;
                        ++new_cnt;
                    }
                    ++cnt;
                }

            }
            catch (Exception ex)
            {
                FileLog.Error("Error processing VisiBox events: ", ex);
            }

            // Clear all VisiBox data that has been saved to the local database.
            visi_box.clearEvents(visi_board.VisiBoxKey, visi_board.VisiBoxDate);

            _processing_visibox_events = false;

            Offline = visi_board.IsOffline;

            if (new_cnt > 0)
            {
                syncData(null, null);

                OnPropertyChanged("CurrentRemaining");
                OnPropertyChanged("NextRemaining");

                if (visi_board.IsMachineRunning)
                {
                    hideDialog();

                    CircularVisibility = Visibility.Collapsed;
                    CountDownTimerVisibility = Visibility.Collapsed;
                    OnPropertyChanged("DowntimeVisibility");
                    OnPropertyChanged("HeaderBrush");
                    OnPropertyChanged("HeaderTextBrush");
                }
                else
                {
                    OnPropertyChanged("DowntimeDescription");
                    OnPropertyChanged("DowntimeBackground");
                    OnPropertyChanged("DowntimeForeground");
                    OnPropertyChanged("DowntimeVisibility");
                    OnPropertyChanged("HeaderBrush");
                    OnPropertyChanged("HeaderTextBrush");

                    if (visi_board.IsLoadUnload && CircularVisibility != Visibility.Visible)
                    {
                        hideDialog();
                        CircularVisibility = visi_board.IsOnBreak ? Visibility.Collapsed : Visibility.Visible;
                    }
                    else
                    {
                        showDowntimeDialog(true, true);
                    }
                }

            }

            return true;
        }

        public void handleCircularProgressUpdates(object send, EventArgs args)
        {
            var evt = (VNet.VisiSuite.Controls.CircularProgessChart.ProgressEvent)args;
            var visi_board = BusinessLogic.VisiBoard.instance();

            if (evt.EventType == VNet.VisiSuite.Controls.CircularProgessChart.ProgressEvent.ProgressStateEnum.LoadUnloadToleranceStart)
            {
                visi_board.updateStateToLoadUnloadTolerance(evt.Seconds);
            }
            else if (evt.EventType == VNet.VisiSuite.Controls.CircularProgessChart.ProgressEvent.ProgressStateEnum.LoadUnloadOverRunStart)
            {
                if (visi_board.updateStateToLoadUnloadOverrun(evt.Seconds))
                {
                    OnPropertyChanged("DowntimeDescription");
                    OnPropertyChanged("DowntimeBackground");
                    OnPropertyChanged("DowntimeForeground");
                    OnPropertyChanged("DowntimeVisibility");
                    OnPropertyChanged("HeaderBrush");
                    OnPropertyChanged("HeaderTextBrush");
                    showDowntimeDialog(true, true);
                }
            }

        }

        // overload method 
        public void showDowntimeDialog(bool is_from_process_visibox_events, bool hide_progress_bar)
        {
            var visi_board = BusinessLogic.VisiBoard.instance();
            if (!visi_board.IsOnBreak)
            {
                NavigationManager.HidePanel();
                if (hide_progress_bar)
                    CircularVisibility = Visibility.Collapsed;

                _show_dialog = true;
                OnPropertyChanged("DowntimeColumn1");
                OnPropertyChanged("DowntimeColumn2");
                OnPropertyChanged("DowntimeColumn3");

                var dlg = new DowntimeDialogView(is_from_process_visibox_events);
                dlg.setOnClose(onDowntimeDialog, null);
                NavigationManager.showDialog(dlg);
            }
        }
 
        public void showBreakLunchDialog()
        {
            var visi_board = BusinessLogic.VisiBoard.instance();
            ReasonCodeEntity break_lunch = (visi_board != null ? visi_board.Break : null);

            if (break_lunch != null)
            {
                visi_board.endBreak();
                OnPropertyChanged("TasksRight");
                OnPropertyChanged("Operator");
                OnPropertyChanged("DowntimeDescription");
                OnPropertyChanged("DowntimeBackground");
                OnPropertyChanged("DowntimeForeground");
                OnPropertyChanged("DowntimeVisibility");
                OnPropertyChanged("HeaderBrush");
                OnPropertyChanged("HeaderTextBrush");

                if (visi_board.DowntimeReasonDesc == "Changeover")
                {
                    CountDownTimerVisibility = Visibility.Visible;
                }
                else if (visi_board.IsLoadUnload)
                {
                    hideDialog();
                    CircularVisibility = Visibility.Visible;
                }

            }
            else
            {
                NavigationManager.HidePanel();
                CircularVisibility = Visibility.Collapsed;

                _show_dialog = true;
                OnPropertyChanged("DowntimeColumn1");
                OnPropertyChanged("DowntimeColumn2");
                OnPropertyChanged("DowntimeColumn3");

                var dlg = new DowntimeDialogView(false, true);
                dlg.setOnClose(onDowntimeDialog, null);
                NavigationManager.showDialog(dlg);
            }
        }

        public bool getAlarmSettings(List<int> percentages, List<Brush> foregrounds, List<Brush> backgrounds)
        {

            var visi_board = BusinessLogic.VisiBoard.instance();
            var settings = visi_board.getAlarmSettings();
            var is_running = visi_board.IsMachineRunning;
            short percent;
            if (settings != null)
            {
                foreach (var item in settings)
                {
                    // Hack for now
                    percent = is_running ? item.MinPercentage100Good : item.MinPercentage100Bad;
                    if (percent != 0 && percent != 100)
                        percent = 90;
                    percentages.Add(percent);
                    foregrounds.Add(new SolidColorBrush(ColorHelper.StringToColor(item.FontColor, Colors.White)));
                    backgrounds.Add(new SolidColorBrush(ColorHelper.StringToColor(item.Color, Colors.Red)));
                }
            }

            return true;
        }

        #endregion

        #region Callback Methods


        public void showScrapDialog(object obj)
        {
            var index = (int)obj;
            if (index < AxisDetails.Count)
            {
                var axis_detail = AxisDetails[index];
                if (!axis_detail.Good.HasValue || axis_detail.Good.Value <= 0)
                    return;

                DateTime when = axis_detail.StartTime;
                if (DateTime.Now < axis_detail.EndTime)
                    when = DateTime.Now;
                NavigationManager.HidePanel();
                var dlg = new ScrapDialogView(when);
                dlg.setOnClose(onScrapDialog, null);
                NavigationManager.showDialog(dlg);

            }
            
        }


        public void showDowntimeScreen()
        {
            FileLog.Error("showDowntimeScreen()");
            NavigationManager.HidePanel();
            // NavigationManager.NavigateTo(new DowntimeView(), null);
        }

        private void onScrapDialog(VisiDialog dlg, object data)
        {
            var scrap_dlg = (ScrapDialogView)dlg;
            if (scrap_dlg.Cancelled)
            {
                NavigationManager.hideDialog();
            }
            else
            {
               var visi_board = BusinessLogic.VisiBoard.instance();
               visi_board.addScrap(scrap_dlg.ProductionPlanData.ProductionPlanId, scrap_dlg.When, scrap_dlg.Quantity, scrap_dlg.ScrapReasonCode);
               NavigationManager.hideDialog();
            }
        }

        private void onDowntimeDialog(VisiDialog dlg, object data)
        {
            var downtime_dlg = (DowntimeDialogView)dlg;
            var reason = downtime_dlg.SelectedReasonCode;

            if (downtime_dlg.Cancelled || reason == null)
            {
                hideDialog();
            }
            else if (reason.Description == "Changeover")
            {
                CircularVisibility = Visibility.Collapsed;
                CountDownTimerVisibility = Visibility.Collapsed;

                _show_dialog = true;
                OnPropertyChanged("DowntimeColumn1");
                OnPropertyChanged("DowntimeColumn2");
                OnPropertyChanged("DowntimeColumn3");
                
                NavigationManager.HidePanel();
                var change_over = new ChangeoverDialogView(downtime_dlg.IsVisiBoxEvent);
                change_over.setOnClose(onChangeoverDialog, reason);
                NavigationManager.showDialog(change_over);
            }
            else
            {
                CircularVisibility = Visibility.Collapsed;
                CountDownTimerVisibility = Visibility.Collapsed;

                var visi_board = BusinessLogic.VisiBoard.instance();

                if (reason.ShopClockEvent == (short)ReasonCodeItem.ShopClockEventEnum.Out)
                    visi_board.operatorId(null);
                else if (reason.ShopClockEvent == (short)ReasonCodeItem.ShopClockEventEnum.In)
                    visi_board.operatorId(downtime_dlg.OperatorId);
                visi_board.reasonSelected(reason, null, !downtime_dlg.IsVisiBoxEvent);

                hideDialog();

                OnPropertyChanged("TasksRight");
                OnPropertyChanged("Operator");
                OnPropertyChanged("DowntimeDescription");
                OnPropertyChanged("DowntimeBackground");
                OnPropertyChanged("DowntimeForeground");
                OnPropertyChanged("DowntimeVisibility");
                OnPropertyChanged("HeaderBrush");
                OnPropertyChanged("HeaderTextBrush");
            }

        }

        private void onChangeoverDialog(VisiDialog dlg, object data)
        {
            var change_over = (ChangeoverDialogView)dlg;
            var reason = (VNet.VisiSuite.VisiBoard.Dal.EntityClasses.ReasonCodeEntity)data;
            dynamic production_plan = change_over.SelectedProductionPlan;

            if (change_over.Cancelled || production_plan == null)
            {
                hideDialog();
            }
            else
            {
                var visi_board = BusinessLogic.VisiBoard.instance();
                visi_board.operatorId(change_over.OperatorId);
                visi_board.reasonSelected(reason, production_plan.ProductionPlanId, !change_over.IsVisiBoxEvent);

                CountDownTime = TimeSpan.FromSeconds(production_plan.SetupTime);
                CountDownTimerVisibility = Visibility.Visible;

                hideDialog();

                OnPropertyChanged("Operator");

                OnPropertyChanged("DowntimeDescription");
                OnPropertyChanged("DowntimeBackground");
                OnPropertyChanged("DowntimeForeground");
                OnPropertyChanged("DowntimeVisibility");
                OnPropertyChanged("HeaderBrush");
                OnPropertyChanged("HeaderTextBrush");

                _production_plans.Clear();
                OnPropertyChanged("CurrentSku");
                OnPropertyChanged("NextSku");
                OnPropertyChanged("CurrentWorkOrder");
                OnPropertyChanged("NextWorkOrder");
                OnPropertyChanged("CurrentPass");
                OnPropertyChanged("NextPass");
                OnPropertyChanged("CurrentQuantity");
                OnPropertyChanged("NextQuantity");
                OnPropertyChanged("CurrentRemaining");
                OnPropertyChanged("NextRemaining");
                OnPropertyChanged("TargetCycleTime");
                OnPropertyChanged("AverageCycleTime");
                OnPropertyChanged("TargetLoadUnloadTime");
                OnPropertyChanged("AverageLoadUnloadTime");
            }

        }

        private void hideDialog()
        {
            _show_dialog = false;
            OnPropertyChanged("DowntimeColumn1");
            OnPropertyChanged("DowntimeColumn2");
            OnPropertyChanged("DowntimeColumn3");
            NavigationManager.hideDialog();
        }

        #endregion

        #region Navigation Framwork
        public override void OnNavigate(object obj)
        {

            Visibility = Visibility.Collapsed;

        }

        public override void OnLeave()
        {
            // Cleaning up
            var visi_board = BusinessLogic.VisiBoard.instance();
            visi_board.initialize(null);
            _production_meter_refresh_timer.Stop();
            _production_meter_refresh_timer.Tick -= refreshProductionMeter;
        }
        #endregion
    }
}
